#include <iostream>
using std::cout;
using std::endl;

class Data
{
public:
    Data(){
        cout << "Data()" << endl;
    }
    ~Data(){
        cout << "~Data()" << endl;
    }

    int getData() const{ return _data; }
private:
    int _data = 10;
};

class MiddleLayer
{
public:
    MiddleLayer(Data * p)
    : _pdata(p)
    {
        cout << "MiddleLayer(Data*)" << endl;
    }

    ~MiddleLayer(){
        cout << "~MiddleLayer()" << endl;
        if(_pdata){
            delete _pdata;
            _pdata = nullptr;
        }
    }

    Data * operator->(){
        return _pdata;
    }

    Data & operator*(){
        return *_pdata;
    }
    friend class ThirdLayer;
private:
    Data * _pdata;
};

class ThirdLayer
{
public:
    ThirdLayer(MiddleLayer * pml)
    : _pml(pml)
    {
        cout << "ThirdLayer(MiddleLayer*)" << endl;
    }

    ~ThirdLayer(){
        cout << "~ThirdLayer()" << endl;
        if(_pml){
            delete _pml;
            _pml = nullptr;
        }
    }

    MiddleLayer & operator->(){
        return *_pml;
    }

    //目标一
    //一层一层解引用
    /* MiddleLayer & operator*(){ */
    /*     return *_pml; */
    /* } */
    

    //目标二
    //一步到位解引用
    Data & operator*(){
        //利用MiddleLayer类中已经对*进行了重载
        //return *(*_pml);//ok,需要运算符重载作为铺垫
        return *(*_pml)._pdata;//ok，需要声明友元
    }
private:
    MiddleLayer * _pml;
};


void test0(){
    //错误的创建方式，让tl对象接管了栈上的MiddleLayer对象
    //在执行析构时会发生段错误
    /* Data * p1 = new Data(); */
    /* MiddleLayer ml(p1); */
    /* ThirdLayer tl(&ml); */

    ThirdLayer tl(new MiddleLayer(new Data()));
    //前一个operator->()是ThirdLayer的成员函数
    //返回结果为MiddleLayer对象
    //后一个operator->()是MiddleLayer的成员函数
    //返回结果为Data*
    //编译器会自动加入一个->,让Data*调用getData函数
    ((tl.operator->()).operator->())->getData();//本质
    (tl.operator->())->getData();//半本质
    cout << tl->getData() << endl;

#if 0
    //目标一
    //一层一层解引用
    cout << (*(*tl)).getData() << endl;
    //前一个operator*()是ThirdLayer的成员函数
    //返回结果为MiddleLayer对象
    //后一个operator*()是MiddleLayer的成员函数
    //返回结果为Data对象
    cout << ((tl.operator*()).operator*()).getData() << endl;
#endif 



    //目标二
    //一步到位解引用
    cout << (*tl).getData() << endl;
    /* cout << (tl.operator*()).getData() << endl;//本质 */
}




void test1(){
    Data * p1 = new Data();
    cout << p1->getData() << endl;
    cout << (*p1).getData() << endl;
    delete p1;

    MiddleLayer ml(new Data());
    cout << ml->getData() << endl;
    /* cout << (ml.operator->())->getData() << endl;//本质 */
    cout << (*ml).getData() << endl;
    /* cout << (ml.operator*()).getData() << endl;//本质 */
}

int main(void){
    test0();
    return 0;
}
